﻿using System;
using System.Runtime.CompilerServices;

namespace C4Net.Framework.Core.Log
{
    /// <summary>
    /// Base abstract class for ILoggable implementations.
    /// </summary>
    public abstract class LoggableBase : ILoggable
    {
        #region - Constants -

        /// <summary>
        /// Name for the default logger.
        /// </summary>
        public static readonly string DefaultLoggerName = "default";

        #endregion

        #region - Methods -

        /// <summary>
        /// Writes a message into the log given the logger name, the severity and the message.
        /// </summary>
        /// <param name="loggerName">Name of the logger.</param>
        /// <param name="severity">The severity.</param>
        /// <param name="message">The message.</param>
        protected abstract void InnerWriteLog(string loggerName, LogSeverity severity, string message);

        /// <summary>
        /// Builds a message entry given the name of the class that originates the message, the name of 
        /// the method and message
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <returns></returns>
        protected string BuildMessage(string message, string className, string memberName)
        {
            if (className == "")
            {
                return message;
            }
            else
            {
                return "[" + className + "." + memberName + "()] " + message;
            }
        }

        /// <summary>
        /// Writes a message into a given logger.
        /// </summary>
        /// <param name="loggerName">Name of the logger.</param>
        /// <param name="severity">The severity of the issue.</param>
        /// <param name="message">The message.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void WriteLog(string loggerName, LogSeverity severity, string message, string className = "", [CallerMemberName] string memberName = "")
        {
            this.InnerWriteLog(loggerName, severity, this.BuildMessage(message, className, memberName));
        }

        /// <summary>
        /// Writes an exception into a given logger.
        /// </summary>
        /// <param name="loggerName">Name of the logger.</param>
        /// <param name="severity">The severity of the issue.</param>
        /// <param name="ex">The exception.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void WriteLog(string loggerName, LogSeverity severity, Exception ex, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(loggerName, severity, ex.Message, className, memberName);
        }

        /// <summary>
        /// Writes a message into the default logger.
        /// </summary>
        /// <param name="severity">The severity of the issue.</param>
        /// <param name="message">The message.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void WriteLog(LogSeverity severity, string message, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(DefaultLoggerName, severity, message, className, memberName);
        }

        /// <summary>
        /// Writes an exception to the default logger.
        /// </summary>
        /// <param name="severity">The severity of the issue.</param>
        /// <param name="ex">The exception.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void WriteLog(LogSeverity severity, Exception ex, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(DefaultLoggerName, severity, ex, className, memberName);
        }

        /// <summary>
        /// Logs a debug message into the default logger.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void LogDebug(string message, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(LogSeverity.Debug, message, className, memberName);
        }

        /// <summary>
        /// Logs a debug exception into the default logger.
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void LogDebug(Exception ex, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(LogSeverity.Debug, ex, className, memberName);
        }

        /// <summary>
        /// Logs an information message into the default logger.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void LogInfo(string message, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(LogSeverity.Info, message, className, memberName);
        }

        /// <summary>
        /// Logs an information exception into the default logger.
        /// </summary>
        /// <param name="ex">The exception.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void LogInfo(Exception ex, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(LogSeverity.Info, ex, className, memberName);
        }

        /// <summary>
        /// Logs a warning message into the default logger.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void LogWarning(string message, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(LogSeverity.Warning, message, className, memberName);
        }

        /// <summary>
        /// Logs a warning exception into the default logger.
        /// </summary>
        /// <param name="ex">The exception.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void LogWarning(Exception ex, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(LogSeverity.Warning, ex, className, memberName);
        }

        /// <summary>
        /// Logs an error message into the default logger.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void LogError(string message, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(LogSeverity.Error, message, className, memberName);
        }

        /// <summary>
        /// Logs an error exception into the default logger.
        /// </summary>
        /// <param name="ex">The exception.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void LogError(Exception ex, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(LogSeverity.Error, ex, className, memberName);
        }

        /// <summary>
        /// Logs a fatal message into the default logger.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void LogFatal(string message, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(LogSeverity.Fatal, message, className, memberName);
        }

        /// <summary>
        /// Logs a fatal exception into the default logger.
        /// </summary>
        /// <param name="ex">The exception.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public void LogFatal(Exception ex, string className = "", [CallerMemberName] string memberName = "")
        {
            this.WriteLog(LogSeverity.Fatal, ex, className, memberName);
        }

        #endregion
    }
}
